1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public class PowTests {
32 private PowTests(){}
33
34 static final double infinityD = Double.POSITIVE_INFINITY;
35
36 static int testPowCase(double input1, double input2, double expected) {
37 int failures = 0;
38 failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
39 StrictMath.pow(input1, input2), expected);
40 failures += Tests.test("Math.pow(double, double)", input1, input2,
41 Math.pow(input1, input2), expected);
42 return failures;
43 }
44
45
46 static int testStrictPowCase(double input1, double input2, double expected) {
47 int failures = 0;
48 failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
49 StrictMath.pow(input1, input2), expected);
50 return failures;
51 }
52
53 static int testNonstrictPowCase(double input1, double input2, double expected) {
54 int failures = 0;
55 failures += Tests.test("Math.pow(double, double)", input1, input2,
56 Math.pow(input1, input2), expected);
57 return failures;
58 }
59
60
61
62
63 static int testPow() {
64 int failures = 0;
65
66 double [][] testCases = {
67 {-0.0, 3.0, -0.0},
68 {-0.0, 4.0, 0.0},
69 {-infinityD, -3.0, -0.0},
70 {-infinityD, -4.0, 0.0},
71 };
72
73 for (double[] testCase : testCases) {
74 failures+=testPowCase(testCase[0], testCase[1], testCase[2]);
75 }
76
77 return failures;
78 }
79
80
81
82
83 static int testCrossProduct() {
84 int failures = 0;
85
86 double testData[] = {
87 Double.NEGATIVE_INFINITY,
88 -Double.MAX_VALUE,
89 (double)Long.MIN_VALUE,
90 (double) -((1L<<53)+2L),
91 (double) -((1L<<53)),
92 (double) -((1L<<53)-1L),
93 -((double)Integer.MAX_VALUE + 4.0),
94 (double)Integer.MIN_VALUE - 1.0,
95 (double)Integer.MIN_VALUE,
96 (double)Integer.MIN_VALUE + 1.0,
97 -Math.PI,
98 -3.0,
99 -Math.E,
100 -2.0,
101 -1.0000000000000004,
102 -1.0000000000000002,
103 -1.0,
104 -0.9999999999999999,
105 -0.9999999999999998,
106 -0.5,
107 -1.0/3.0,
108 -Double.MIN_VALUE,
109 -0.0,
110 +0.0,
111 +Double.MIN_VALUE,
112 +1.0/3.0,
113 +0.5,
114 +0.9999999999999998,
115 +0.9999999999999999,
116 +1.0,
117 +1.0000000000000002,
118 +1.0000000000000004,
119 +2.0,
120 +Math.E,
121 +3.0,
122 +Math.PI,
123 -(double)Integer.MIN_VALUE - 1.0,
124 -(double)Integer.MIN_VALUE,
125 -(double)Integer.MIN_VALUE + 1.0,
126 (double)Integer.MAX_VALUE + 4.0,
127 (double) ((1L<<53)-1L),
128 (double) ((1L<<53)),
129 (double) ((1L<<53)+2L),
130 -(double)Long.MIN_VALUE,
131 Double.MAX_VALUE,
132 Double.POSITIVE_INFINITY,
133 Double.NaN
134 };
135
136 double NaN = Double.NaN;
137 for(double x: testData) {
138 for(double y: testData) {
139 boolean testPass = false;
140 double expected=NaN;
141 double actual;
142
143
144 if( Double.isNaN(y)) {
145 expected = NaN;
146 } else if (y == 0.0) {
147 expected = 1.0;
148 } else if (Double.isInfinite(y) ) {
149 if(y > 0) {
150 if (Math.abs(x) > 1.0) {
151 expected = Double.POSITIVE_INFINITY;
152 } else if (Math.abs(x) == 1.0) {
153 expected = NaN;
154 } else if (Math.abs(x) < 1.0) {
155 expected = +0.0;
156 } else {
157 assert Double.isNaN(x);
158 expected = NaN;
159 }
160 } else {
161 if (Math.abs(x) > 1.0) {
162 expected = +0.0;
163 } else if (Math.abs(x) == 1.0) {
164 expected = NaN;
165 } else if (Math.abs(x) < 1.0) {
166 expected = Double.POSITIVE_INFINITY;
167 } else {
168 assert Double.isNaN(x);
169 expected = NaN;
170 }
171 }
172 } else if (y == 1.0) {
173 expected = x;
174 } else if (Double.isNaN(x)) {
175 assert y != 0.0;
176 expected = NaN;
177 } else if (x == Double.NEGATIVE_INFINITY) {
178 expected = (y < 0.0) ? f2(y) :f1(y);
179 } else if (x == Double.POSITIVE_INFINITY) {
180 expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY;
181 } else if (equivalent(x, +0.0)) {
182 assert y != 0.0;
183 expected = (y < 0.0) ? Double.POSITIVE_INFINITY: +0.0;
184 } else if (equivalent(x, -0.0)) {
185 assert y != 0.0;
186 expected = (y < 0.0) ? f1(y): f2(y);
187 } else if( x < 0.0) {
188 assert y != 0.0;
189 failures += testStrictPowCase(x, y, f3(x, y));
190 failures += testNonstrictPowCase(x, y, f3ns(x, y));
191 continue;
192 } else {
193
194 expected = NaN;
195 continue;
196 }
197
198 failures += testPowCase(x, y, expected);
199 }
200 }
201 return failures;
202 }
203
204 static boolean equivalent(double a, double b) {
205 return Double.compare(a, b) == 0;
206 }
207
208 static double f1(double y) {
209 return (intClassify(y) == 1)?
210 Double.NEGATIVE_INFINITY:
211 Double.POSITIVE_INFINITY;
212 }
213
214
215 static double f2(double y) {
216 return (intClassify(y) == 1)?-0.0:0.0;
217 }
218
219 static double f3(double x, double y) {
220 switch( intClassify(y) ) {
221 case 0:
222 return StrictMath.pow(Math.abs(x), y);
223
224
225 case 1:
226 return -StrictMath.pow(Math.abs(x), y);
227
228
229 case -1:
230 return Double.NaN;
231
232
233 default:
234 throw new AssertionError("Bad classification.");
235
236 }
237 }
238
239 static double f3ns(double x, double y) {
240 switch( intClassify(y) ) {
241 case 0:
242 return Math.pow(Math.abs(x), y);
243
244
245 case 1:
246 return -Math.pow(Math.abs(x), y);
247
248
249 case -1:
250 return Double.NaN;
251
252
253 default:
254 throw new AssertionError("Bad classification.");
255
256 }
257 }
258
259 static boolean isFinite(double a) {
260 return (0.0*a == 0);
261 }
262
263
264
265
266
267 static int intClassify(double a) {
268 if(!isFinite(a) ||
269 (a != Math.floor(a) )) {
270 return -1;
271 }
272 else {
273
274
275 a = StrictMath.abs(a);
276
277 if(a+1.0 == a) {
278 return 0;
279 }
280 else {
281 long ell = (long) a;
282 return ((ell & 0x1L) == (long)1)?1:0;
283 }
284 }
285 }
286
287 public static void main(String [] argv) {
288 int failures = 0;
289
290 failures += testPow();
291 failures += testCrossProduct();
292
293 if (failures > 0) {
294 System.err.println("Testing pow incurred "
295 + failures + " failures.");
296 throw new RuntimeException();
297 }
298 }
299 }